home *** CD-ROM | disk | FTP | other *** search
/ Programming Sound Cards / Programming Sound Cards.iso / sound_52 / bend.ma < prev    next >
Text File  |  1995-01-01  |  18KB  |  617 lines

  1. #
  2. # bendlib.ma - (dx7) pitch bend library of Ravel routines
  3. #
  4. # Implementation Assumptions:
  5. #
  6. # 1. Setup for dx7 type instrument.
  7. # might work elsewhere as is but may take some changes.
  8. #
  9. # 2. check SEMITONEUNITS; i.e., no of pitch bend
  10. # units per semitone. We set poff to 1.
  11. #
  12. # 3. Assume that
  13. # dx7 is setup as follows:
  14. #    range 12 (an octave span for the bend)
  15. #    step 0 - continuous bend (not semitones)
  16. #
  17. #########################################
  18. # Functions supported:
  19. ##############################################################
  20. # 1. riff vibratto(note, bendTime, totalTime, vibrattoStep, velocity)
  21. #    vibrato on specified note. note issued here.
  22. #
  23. # 2. riff vnonote(firstNote, curbend, totalTime, vibrattoStep, velocity)
  24. #    vibratto on note already issued.
  25. #
  26. # 3. riff bendUp(firstNote, firstTime, bendTime, totalTime, interval, velocity, vibrattoFlag, vibrattoSteps)
  27. #    pitch bend up of interval of 1-12 semitones
  28. #
  29. # 4. riff bendDown(firstNote, firstTime, bendTime, totalTime, interval, velocity, vibrattoFlag, vibrattoSteps)
  30. #    pitch bend down of interval of 1-12 semitones
  31. #
  32. # 5. riff bendUpDown(firstNote, firstTime, bendTime, totalTime, interval, velocity, vibrattoFlag, vibrattoSteps)
  33. #    pitch bend up then down. Jan Hammer would like it. 
  34. #
  35. # There are also some test routines at the bottom with a test vco
  36. # driver.
  37. # They can function as examples of how to use the above riffs.
  38. # You might want to comment them out to reduce code size.
  39.  
  40. export
  41.     vibratto,        # riff
  42.     vnonote,        # riff
  43.     bendUp,            # riff
  44.     bendDown,        # riff
  45.     bendUpDown         # riff
  46. end
  47.  
  48. # bend units per semi-tone 
  49. SEMITONEUNITS = 680
  50. # bend units per whole-tone 
  51. WHOLETONEUNITS = 1360
  52. # bend units at pitchbend center
  53. BENDCENTER = 8192
  54.  
  55. #
  56. # vibratto - play vibratto around requested tone.
  57. #
  58. # time is broken up into two parts, bendTime and remainder.
  59. # bendTime comes first. This permits vibratto followed by
  60. # normal non-vibratto tone.
  61. #
  62. # vibrattoStep - range of bend around center tone.
  63. #    10 - minimum
  64. #    60 - medium
  65. #    100 - heavy
  66. riff vibratto(firstNote, bendTime, totalTime, vibrattoStep, velocity)
  67. # interval - number of semitones to bend up
  68.     int events
  69.     int bendIncrement
  70.     int curincrement
  71.     int bendvalue
  72.     int elapsedTime
  73.     int remainingTime
  74.  
  75.     # make sure pitch bend offset is set at 1 so
  76.     # that we use the true MIDI numbers in decimal
  77.     # Remember this is a compiler pseudo-op.
  78.     poff 1
  79.  
  80.     bendIncrement = vibrattoStep
  81.  
  82.     # play note with 0 eventime    
  83.     # the note lasts "totalTime" time before a noteoff
  84.     # is issued
  85.     note firstNote    0,totalTime        velocity
  86.  
  87.     bendvalue = BENDCENTER
  88.     # start off with pitch bend wheel centered
  89.     # take no time to do this
  90.     bend    0    BENDCENTER
  91.  
  92.     # loop through pitch bend up
  93.     elapsedTime = 0
  94.     for ( events = 0; events < bendTime; events++)
  95.         # alternate up/down around pitch
  96.         if ({events % 2} == 0)
  97.             bend 1 BENDCENTER+bendIncrement
  98.         else
  99.             bend 1 BENDCENTER-bendIncrement 
  100.         end
  101.         elapsedTime++
  102.     end
  103.     # issue another pitch bend to make sure we
  104.     # arrived where we want because for loop
  105.     # above may not have arrived precisely
  106.     bend 0    BENDCENTER 
  107.     # use bend constant to return pitchbend wheel to center
  108.     poff 1
  109.     # deterime amount of eventtime remaining
  110.     # we may have some slop if the amount of time
  111.     # spent playing bends did not equal the bendTime
  112.     if (elapsedTime == bendTime)
  113.         remainingTime = totalTime - bendTime
  114.     else
  115.         remainingTime = {bendTime - elapsedTime} + {totalTime - bendTime}
  116.     end
  117.     # tie note for remaining time
  118.     tie  remainingTime
  119. #     void printf("bend %d \n",BENDCENTER)
  120.     # issue rest to make sure noteoff in effect. this
  121.     # is paranoia most likely
  122.     rest 0
  123.     # put pitchbend wheel at center
  124.     bend 0 BENDCENTER
  125. #    void dumptime()
  126. end
  127.  
  128. #
  129. # vnonote - play vibratto around requested tone. Used
  130. #    by other bend routines. Does not issue initial note.
  131. #    Also assumes that we do pitch bend for entire totalTime.
  132. #    I.e., not broken up into pitch bend, no pitch bend step.
  133. #
  134. # vibrattoStep - range of bend around center tone.
  135. #    10 - minimum
  136. #    60 - medium
  137. #    100 - heavy
  138. riff vnonote(firstNote, curbend, totalTime, vibrattoStep, velocity)
  139. # interval - number of semitones to bend up
  140.     int events
  141.     int bendvalue
  142.     int bendIncrement
  143.     int elapsedTime
  144.     int remainingTime
  145.  
  146.     # make sure pitch bend offset is set at 1 so
  147.     # that we use the true MIDI numbers in decimal
  148.     poff 1
  149.  
  150.     bendIncrement = vibrattoStep
  151.  
  152.     bendvalue = curbend
  153.  
  154.     # loop through pitch bend up
  155.     for ( events = 0; events < totalTime; events++)
  156.         # alternate up/down around pitch
  157.         if ({events % 2} == 0)
  158.             bend 1 bendvalue+bendIncrement
  159.         else
  160.             bend 1 bendvalue-bendIncrement 
  161.         end
  162.     end
  163.     # issue another pitch bend to make sure we
  164.     # arrived where we want because for loop
  165.     # above may not have arrived precisely
  166.     bend 0    bendvalue 
  167.     # issue rest to make sure noteoff in effect. this
  168.     # is paranoia most likely
  169.     rest 0
  170. #    void dumptime()
  171.     bend 0 BENDCENTER
  172. end
  173.  
  174. #
  175. # bendUp according to specified interval.
  176. #
  177. # Eventtime is broken up according to following scheme.
  178. #
  179. #    1. issue note for firstTime events
  180. #    2. bend for bendTime events
  181. #    3. tie for remaining time (totalTime - (firstTime + bendTime)
  182. #    Latter non-bend time may have vibratto attached.
  183. #
  184. # e.g.,
  185. #    C, e, e, q, 2, 100, 0, 0 
  186. #
  187. # would mean play C for e events, then bend to D for e events,
  188. # and quit with no vibratto at end.
  189. #
  190. # firstnote - starting note
  191. # firstTime - time devoted to first note before bend
  192. # bendTime - period of time for bends
  193. # totalTime - total elapsed time for note to note. If totalTime
  194. #    is larger than bendTime, we do the pitch bend first
  195. #    and spend the remaining amount of time on the note.
  196. # interval - 1..12 semitones.
  197. # velocity - desired velocity.
  198. # vibratto - flag, 1 for TRUE, 0 for FALSE, if specified
  199. # then we use vibratto for last totalTime-bendTime period.
  200. # This permits more guitar-like effects.
  201. # vibrattoStep - how much pitch bend for vibratto
  202. #
  203. # bendUp(C, 0, h, w, 12, 100, 0, 0)
  204. # would execute a linear bend from C to HC for the first 'h'
  205. # of time, and then execute the HC for the 2nd 'h' with
  206. # total elapsed time of 'w'.
  207. #
  208. # Algorithm needs work but this gets the job done.
  209. #
  210.  
  211. riff bendUp(firstNote, firstTime, bendTime, totalTime, interval, velocity, vflag, vsteps)
  212. # interval - number of semitones to bend up
  213.     int events
  214.     int bendIncrement
  215.     int totalBendUnits
  216.     int pertimeClick
  217.     int curincrement
  218.     int bendvalue
  219.     int elapsedTime
  220.     int remainingTime
  221.  
  222.     # make sure pitch bend offset is set at 1 so
  223.     # that we use the true MIDI numbers in decimal
  224.     poff 1
  225.  
  226.     # don't set interval to 0
  227.     if (interval == 0)
  228.         void printf("bendUp: invalid 0 interval\n")
  229.         final
  230.     end
  231.     # total number of bend units to cover interval
  232.     totalBendUnits = interval * SEMITONEUNITS
  233.  
  234.     # determine per bend event time and how much
  235.     # to bend per bend call
  236.     # if more time than total bend units according
  237.     # to the interval, then divide the time
  238.     # by the number of bend units to get the per
  239.     # bend call time, otherwise time is 1
  240.     if (bendTime > totalBendUnits)
  241.         pertimeClick = bendTime / totalBendUnits
  242.         bendIncrement = totalBendUnits / pertimeClick
  243.     else
  244.         bendIncrement = totalBendUnits / bendTime
  245.         pertimeClick = 1
  246.     end
  247.  
  248. #     void printf("bendIncrement %d\n",bendIncrement)
  249. #     void printf("pertimeClick %d\n",pertimeClick)
  250. #     void printf("totalBendUnits %d\n",totalBendUnits)
  251.  
  252.     # play note with 0 eventime    
  253.     # the note lasts "totalTime" time before a noteoff
  254.     # is issued
  255.     note firstNote    firstTime,totalTime        velocity
  256. #    void dumptime()
  257.     bendvalue = BENDCENTER
  258.     # start off with pitch bend wheel centered
  259.     # take no time to do this
  260.     poff 1
  261.     bend    0    BENDCENTER
  262.     curincrement = bendIncrement
  263.     # loop through pitch bend up
  264.     elapsedTime = 0
  265.     for ( events = 0; events < bendTime; events++)
  266.         bend pertimeClick BENDCENTER+curincrement 
  267. #        void printf("%d %d\n",pertimeClick,BENDCENTER+curincrement)
  268.         curincrement = curincrement + bendIncrement
  269.         elapsedTime = elapsedTime + pertimeClick
  270.     end
  271.     # issue another pitch bend to make sure we
  272.     # arrived where we want because for loop
  273.     # above may not have arrived precisely
  274.     bend 0    BENDCENTER + totalBendUnits
  275.  
  276.  
  277.     # use bend constant to return pitchbend wheel to center
  278.     poff 1
  279.     # deterime amount of eventtime remaining
  280.     # we may have some slop if the amount of time
  281.     # spent playing bends did not equal the bendTime
  282.     if (elapsedTime == bendTime)
  283.         remainingTime = totalTime - {firstTime + bendTime}
  284.     else
  285.         remainingTime = {bendTime - elapsedTime} + {totalTime - {bendTime + firstTime}}
  286.     end
  287.     # do vibratto for last half
  288.     # use special vibratto routine that does not issue note
  289.     # just bends
  290.     if (vflag)
  291.         void vnonote(firstNote, BENDCENTER+totalBendUnits, remainingTime, vsteps, velocity)
  292.         return(0)
  293.     end
  294.     # tie note for remaining time
  295.     tie  remainingTime
  296. #     void printf("bend %d \n",BENDCENTER)
  297.     # issue rest to make sure noteoff in effect. this
  298.     # is paranoia most likely
  299.     rest 0
  300.     # put pitchbend wheel at center
  301.     bend 0 BENDCENTER
  302. #    void dumptime()
  303. end
  304.  
  305. #
  306. # bend Down requested interval
  307. #
  308. # interval 0..12: max range an octave
  309. riff bendDown(firstNote, firstTime, bendTime, totalTime, interval, velocity, vflag, vsteps)
  310. # interval - number of semitones to bend up
  311.     int events
  312.     int bendIncrement
  313.     int totalBendUnits
  314.     int pertimeClick
  315.     int curincrement
  316.     int bendvalue
  317.     int elapsedTime
  318.     int remainingTime
  319.  
  320.     # make sure pitch bend offset is set at 1 so
  321.     # that we use the true MIDI numbers in decimal
  322.     poff 1
  323.  
  324.     # don't set interval to 0
  325.     if (interval == 0)
  326.         void printf("bendUp: invalid 0 interval\n")
  327.         final
  328.     end
  329.     # total number of bend units to cover interval
  330.     totalBendUnits = interval * SEMITONEUNITS
  331.  
  332.     # determine per bend event time and how much
  333.     # to bend per bend call
  334.     # if more time than total bend units according
  335.     # to the interval, then divide the time
  336.     # by the number of bend units to get the per
  337.     # bend call time, otherwise time is 1
  338.     if (bendTime > totalBendUnits)
  339.         pertimeClick = bendTime / totalBendUnits
  340.         bendIncrement = totalBendUnits / pertimeClick
  341.     else
  342.         bendIncrement = totalBendUnits / bendTime
  343.         pertimeClick = 1
  344.     end
  345.  
  346. #     void printf("bendIncrement %d\n",bendIncrement)
  347. #     void printf("pertimeClick %d\n",pertimeClick)
  348. #     void printf("totalBendUnits %d\n",totalBendUnits)
  349.  
  350.     # play note with 0 eventime    
  351.     # the note lasts "totalTime" time before a noteoff
  352.     # is issued
  353.     note firstNote    firstTime, totalTime        velocity
  354. #    void dumptime()
  355.     bendvalue = BENDCENTER
  356.     # start off with pitch bend wheel centered
  357.     # take no time to do this
  358.     poff 1
  359.     bend    0    BENDCENTER
  360.     curincrement = bendIncrement
  361.     # loop through pitch bend up
  362.     elapsedTime = 0
  363.     for ( events = 0; events < bendTime; events++)
  364.         bend pertimeClick BENDCENTER-curincrement 
  365. #        void printf("%d %d\n",pertimeClick,BENDCENTER+curincrement)
  366.         curincrement = curincrement + bendIncrement
  367.         elapsedTime = elapsedTime + pertimeClick
  368.     end
  369.     # issue another pitch bend to make sure we
  370.     # arrived where we want because for loop
  371.     # above may not have arrived precisely
  372.     bend 0    BENDCENTER - totalBendUnits
  373. #    void printf("%d \n",BENDCENTER+totalBendUnits)
  374.     # use bend constant to return pitchbend wheel to center
  375.     poff 1
  376.     # deterime amount of eventtime remaining
  377.     # we may have some slop if the amount of time
  378.     # spent playing bends did not equal the bendTime
  379.     if (elapsedTime == bendTime)
  380.         remainingTime = totalTime - {firstTime + bendTime}
  381.     else
  382.         remainingTime = {bendTime - elapsedTime} + {totalTime - {bendTime + firstTime}}
  383.     end
  384.     # do vibratto for last half
  385.     # use special vibratto routine that does not issue note
  386.     # just bends
  387.     if (vflag)
  388.         void vnonote(firstNote, BENDCENTER-totalBendUnits, remainingTime, vsteps, velocity)
  389.         return(0)
  390.     end
  391.     # tie note for remaining time
  392.     tie  remainingTime
  393. #     void printf("bend %d \n",BENDCENTER)
  394.     # issue rest to make sure noteoff in effect. this
  395.     # is paranoia most likely
  396.     rest 0
  397.     # put pitchbend wheel at center
  398.     bend 0 BENDCENTER
  399. #    void dumptime()
  400. end
  401.  
  402. #
  403. # bendUpDown
  404. #
  405. # bend up interval requested
  406. # then bend down
  407. #
  408. riff bendUpDown(firstNote, firstTime, bendTime, totalTime, interval, velocity, vflag, vsteps)
  409. # interval - number of semitones to bend up
  410.     int events
  411.     int bendIncrement
  412.     int totalBendUnits
  413.     int pertimeClick
  414.     int curincrement
  415.     int bendvalue
  416.     int elapsedTime
  417.     int remainingTime
  418.     int firstHalf    # first half of time delta
  419.     int secondHalf    # second half of time delta
  420.  
  421.     # make sure pitch bend offset is set at 1 so
  422.     # that we use the true MIDI numbers in decimal
  423.     poff 1
  424.  
  425.     # don't set interval to 0
  426.     if (interval == 0)
  427.         void printf("bendUp: invalid 0 interval\n")
  428.         final
  429.     end
  430.  
  431.     # split bend timedelta into first half and second
  432.     # half and make sure all events are accounted for
  433.     # in time
  434.     firstHalf = bendTime >> 1
  435.     if ({bendTime % 2} != 0)
  436.         secondHalf = firstHalf + 1
  437.     else
  438.         secondHalf = firstHalf
  439.     end
  440.  
  441.     # total number of bend units to cover interval
  442.     totalBendUnits = interval * SEMITONEUNITS
  443.  
  444.     # determine per bend event time and how much
  445.     # to bend per bend call
  446.     # if more time than total bend units according
  447.     # to the interval, then divide the time
  448.     # by the number of bend units to get the per
  449.     # bend call time, otherwise time is 1
  450.     if (firstHalf > totalBendUnits)
  451.         pertimeClick = firstHalf / totalBendUnits
  452.         bendIncrement = totalBendUnits / pertimeClick
  453.     else
  454.         bendIncrement = totalBendUnits / firstHalf
  455.         pertimeClick = 1
  456.     end
  457.  
  458. #     void printf("bendIncrement %d\n",bendIncrement)
  459. #     void printf("pertimeClick %d\n",pertimeClick)
  460. #     void printf("totalBendUnits %d\n",totalBendUnits)
  461.  
  462.     # play note with 0 eventime    
  463.     # the note lasts "totalTime" time before a noteoff
  464.     # is issued
  465.     note firstNote    firstTime,totalTime        velocity
  466. #    void dumptime()
  467.     bendvalue = BENDCENTER
  468.     # start off with pitch bend wheel centered
  469.     # take no time to do this
  470.     poff 1
  471.     bend    0    BENDCENTER
  472.     curincrement = bendIncrement
  473.     # loop through pitch bend up
  474.     elapsedTime = 0
  475.     for ( events = 0; events < firstHalf; events++)
  476.         bend pertimeClick BENDCENTER+curincrement 
  477. #        void printf("%d %d\n",pertimeClick,BENDCENTER+curincrement)
  478.         curincrement = curincrement + bendIncrement
  479.         elapsedTime = elapsedTime + pertimeClick
  480.     end
  481.  
  482.     # make sure we got to top
  483.     bend 0    BENDCENTER + totalBendUnits
  484.     curincrement = totalBendUnits
  485.  
  486.     # now loop down, keep running totals
  487.     for ( events = 0; events < secondHalf; events++)
  488.         bend pertimeClick BENDCENTER+curincrement
  489. #        void printf("%d %d\n",pertimeClick,BENDCENTER+curincrement)
  490.         curincrement = curincrement - bendIncrement
  491.         elapsedTime = elapsedTime + pertimeClick
  492.     end
  493.  
  494.     # issue another pitch bend to make sure we
  495.     # arrived where we want because for loop
  496.     # above may not have arrived precisely
  497.     bend 0    BENDCENTER 
  498.  
  499. #    void printf("%d \n",BENDCENTER+totalBendUnits)
  500.     # use bend constant to return pitchbend wheel to center
  501.     poff 1
  502.     # deterime amount of eventtime remaining
  503.     # we may have some slop if the amount of time
  504.     # spent playing bends did not equal the bendTime
  505.     if (elapsedTime == bendTime)
  506.         remainingTime = totalTime - {firstTime + bendTime}
  507.     else
  508.         remainingTime = {bendTime - elapsedTime} + {totalTime - {bendTime + firstTime}}
  509.     end
  510.     if (vflag)
  511.         void vnonote(firstNote, BENDCENTER, remainingTime, vsteps, velocity)
  512.         return(0)
  513.     end
  514.  
  515.     # tie note for remaining time
  516.     tie  remainingTime
  517. #     void printf("bend %d \n",BENDCENTER)
  518.     # issue rest to make sure noteoff in effect. this
  519.     # is paranoia most likely
  520.     rest 0
  521.     # put pitchbend wheel at center
  522.     bend 0 BENDCENTER
  523. #    void dumptime()
  524. end
  525.  
  526.  
  527. # should start with 4 note chord from LLC to LC range
  528. # LLC, LE, LG, LC to LC, E, G, HC octave bend. Fun.
  529. # then play major scale via bends twice.
  530. # finish off with normal C to HC for contrast
  531. #
  532. riff testBendUp()
  533.     int i
  534.     void printf("C chord bend up\n")
  535.     LG    0,w
  536.     LE    0,w
  537.     LLC    0,w
  538.     void bendUp(LC, 0, h, w, 12, 100, 0, 0)
  539.     void printf("C scale down twice\n")
  540.     for ( i = 0; i < 2; i++)
  541.         C    q
  542.         # up to D
  543.         void bendUp(C, 0, e, q, 2, 100, 0, 0)
  544.         # up to E
  545.         void bendUp(D, 0, e, q, 2, 100, 0, 0)
  546.         # up to F
  547.         void bendUp(E, 0, e, q, 1, 100, 0, 0)
  548.         void bendUp(F, 0, e, q, 2, 100, 0, 0)
  549.         void bendUp(G, 0, e, q, 2, 100, 0, 0)
  550.         void bendUp(A, 0, e, q, 2, 100, 0, 0)
  551.         void bendUp(B, 0, e, q, 1, 100, 0, 0)
  552.     end
  553.     void printf("C HC reference tones\n")
  554.     C    q
  555.     HC    q
  556.  
  557. end
  558.  
  559. riff testBendDown()
  560.     void printf("bend down: C scale down to G\n")
  561.     # C
  562.     note C    q    127
  563.     # C to LB
  564.     void bendDown(C, 0, e, q, 1, 127, 0, 0)
  565.     # LB to LA
  566.     void bendDown(LB, 0, e, q, 2, 127, 0, 0)
  567.     # LA to LG
  568.     void printf("bend down: LG scale down to LC\n")
  569.     void bendDown(LA, 0, e, q, 2, 127, 0, 0)
  570.     # LG to LC
  571.     void bendDown(LG, 0, e, q, 7, 127, 0, 0)
  572.  
  573.  
  574.     void printf("C then C to LC\n")
  575.     C    q
  576.     void bendDown(C, 0, q, w, 12, 127, 0, 0) 
  577.     #
  578.     void printf("reference tones LC C \n")
  579.     LC    q
  580.     C    q
  581. end
  582.  
  583. riff testVibratto()
  584.     int vsteps
  585.     int i
  586.     vsteps = 0
  587.     for ( i = 0 ; i < 20; i++)
  588.         void printf("vsteps %d\n",vsteps)
  589.         void vibratto(C, q*3, w, vsteps, 100)
  590.         vsteps = vsteps + 10
  591.     end
  592. end
  593.  
  594. riff testguitarRiff()
  595.     void bendUp(LG, 2, e+2, q, 2, 110, 1, 70)
  596.  
  597.     void vibratto(LA, q,q, 80, 100)
  598.     void vibratto(E, q,q, 60, 100)
  599.     void bendUpDown(D, 3, q+e-3, q+e, 2, 110, 0, 0)
  600.     void vibratto(C, e, e, 50, 100)
  601.     void vibratto(LA, 3*q,3*q, 110, 100)
  602.     rest    e
  603.     void bendUp(LG, 0, e, q+e, 2, 110, 1, 110)
  604. end
  605.  
  606. vco testBendLib()
  607.     void testguitarRiff()
  608.     void testBendUp()
  609.     void testBendDown()
  610.     void testVibratto()
  611. end
  612.  
  613.  
  614.